
﻿﻿//======================================================================
//
//        Copyright : Zhengzhou Strawberry Computer Technology Co.,LTD.
//        All rights reserved
//        
//        Application:NFinal MVC framework
//        Filename :Router.cs
//        Description :路由类
//
//        created by Lucas at  2015-10-15`
//     
//        WebSite:http://www.nfinal.com
//
//======================================================================
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using NFinal;

namespace BlackHtml5
{
#if (!AspNET && !NFinalOwin)
    public static class OwinRouter
    {
        /// <summary>  
        /// 本地时间转成GMT时间  
        /// </summary>  
        public static string ToGmtString(DateTime dt)
        {
            return dt.ToUniversalTime().ToString("r");
        }
        /// <summary>  
        /// 本地时间转成GMT格式的时间  
        /// </summary>  
        public static string ToGmtFormat(DateTime dt)
        {
            return dt.ToString("r") + dt.ToString("zzz").Replace(":", "");
        }
        /// <summary>  
        /// GMT时间转成本地时间  
        /// </summary>  
        /// <param name="gmt">字符串形式的GMT时间</param>  
        /// <returns></returns>  
        public static DateTime Gmt2Local(string gmt)
        {
            DateTime dt = DateTime.MinValue;
            try
            {
                string pattern = "";
                if (gmt.IndexOf("+0") != -1)
                {
                    gmt = gmt.Replace("GMT", "");
                    pattern = "ddd, dd MMM yyyy HH':'mm':'ss zzz";
                }
                if (gmt.ToUpper().IndexOf("GMT") != -1)
                {
                    pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
                }
                if (pattern != "")
                {
                    dt = DateTime.ParseExact(gmt, pattern, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal);
                    dt = dt.ToLocalTime();
                }
                else
                {
                    dt = Convert.ToDateTime(gmt);
                }
            }
            catch
            {
            }
            return dt;
        }
        private static void Callback(IAsyncResult result)
        {
            //结束异步写入
            System.IO.FileStream stream = (System.IO.FileStream)result.AsyncState;
            stream.EndWrite(result);
            stream.Dispose();
        }
		//设置浏览器缓存
        public static void SetBrowerCache(Microsoft.Owin.IOwinContext context, int optimizing,int seconds)
        {
            //浏览器缓存
            if ((optimizing & (int)NFinal.Optimizing.Cache_Brower_Cached) != 0)
            {
                context.Response.Headers.Set("Cache-Control", "public");
                context.Response.Headers.Set("Date",ToGmtString(DateTime.Now));
                //NotModify
                if ((optimizing & (int)NFinal.Optimizing.Cache_Browse_NotModify) != 0)
                {
                    string filename = System.IO.Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, context.Request.PathBase.Value, context.Request.Path.Value);
                    if (System.IO.File.Exists(filename))
                    {
                        System.IO.FileInfo fileInfo = new System.IO.FileInfo(filename);
                        string lastModified = ToGmtString(fileInfo.LastWriteTime);
                        context.Response.Headers.Set("Last-Modified", lastModified);
                    }
                    else
                    {
                        context.Response.Headers.Set("Last-Modified", ToGmtString(DateTime.Now));
                    }
                }
                //Expires
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Browser_Expires) != 0)
                {
                    context.Response.Headers.Set("Expires", ToGmtString(DateTime.Now.AddSeconds(seconds)));
                }
                //NoExpires
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Browser_NoExpires) != 0)
                {
                }
            }
            else
            {
                //不进行缓存
                context.Response.Headers.Set("Cache-Control","private");
            }
        }
        //设置服务器缓存
        public static void SetServerCacheAndOutPut(Microsoft.Owin.IOwinContext context,string url, string query, byte[] buffer, int optimizing, int seconds)
        {
            //服务器缓存
            if ((optimizing & (int)NFinal.Optimizing.Cache_Server_Cached) != 0)
            {
                //FileDependency
                if ((optimizing & (int)NFinal.Optimizing.Cache_Server_FileDependency) != 0)
                {
                    string fileName=null;
					if(url.EndsWith("/"))
					{
						fileName = NFinal.Utility.MapPath(url+"Index.html");
					}
                    else
					{
						fileName = NFinal.Utility.MapPath(url);
					}
					if ((optimizing & (int)NFinal.Optimizing.CompressZip) != 0)
                    {
                        fileName = fileName + ".zip";
                    }
                    else if ((optimizing & (int)NFinal.Optimizing.CompressDeflate) != 0)
                    {
                        fileName = fileName + ".deflate";
                    }
                    //将HTML写入静态文件
                    if (!System.IO.File.Exists(fileName))
                    {
						string dir = System.IO.Path.GetDirectoryName(fileName);
                        if (!System.IO.Directory.Exists(dir))
                        {
                            System.IO.Directory.CreateDirectory(dir);
                        }
                        System.IO.FileStream file = new System.IO.FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite, 1024, true);
                        file.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(Callback), file);
                    }
					if (seconds > 0)
                    {
						//将HTML插入新的缓存
						System.Runtime.Caching.CacheItemPolicy itemPolicy = new System.Runtime.Caching.CacheItemPolicy();
						itemPolicy.ChangeMonitors.Add(new System.Runtime.Caching.HostFileChangeMonitor(new string []{fileName }));
						System.Runtime.Caching.MemoryCache.Default.Set(new System.Runtime.Caching.CacheItem(url+query,buffer),itemPolicy);
					}
                }
                //AbsoluteExpiration
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Server_AbsoluteExpiration) != 0)
                {
                    System.Runtime.Caching.CacheItemPolicy itemPolicy = new System.Runtime.Caching.CacheItemPolicy();
                    itemPolicy.AbsoluteExpiration=DateTimeOffset.Now.AddSeconds(seconds);
                    System.Runtime.Caching.MemoryCache.Default.Set(new System.Runtime.Caching.CacheItem(url+query, buffer), itemPolicy);
                }
                //SlidingExpiration
                else if ((optimizing & (int)NFinal.Optimizing.Cache_Server_SlidingExpiration) != 0)
                {
                    System.Runtime.Caching.CacheItemPolicy itemPolicy = new System.Runtime.Caching.CacheItemPolicy();
                    itemPolicy.SlidingExpiration=new TimeSpan(0, 0, seconds);
                    System.Runtime.Caching.MemoryCache.Default.Set(new System.Runtime.Caching.CacheItem(url+query,buffer),itemPolicy);
                }
            }
            //直接输出
            context.Response.Body.Write(buffer, 0, buffer.Length);
            context.Response.Body.Dispose();
        }
        //写入缓存
        public static bool WriteCache(Microsoft.Owin.IOwinContext context,string url,int optimizing)
        {
            //服务器缓存
            if ((optimizing & (int)NFinal.Optimizing.Cache_Server_Cached) != 0)
            {
                object cache = System.Runtime.Caching.MemoryCache.Default.Get(url);
                //如果缓存存在则直接输出.
                if (cache != null)
                {
                    if ((optimizing & (int)NFinal.Optimizing.Comresssed) != 0)
                    {
                        if ((optimizing & (int)NFinal.Optimizing.CompressZip) != 0)
                        {
                            context.Response.Headers.Append("Content-encoding", "gzip");
                        }
                        else if ((optimizing & (int)NFinal.Optimizing.CompressDeflate) != 0)
                        {
                            context.Response.Headers.Append("Content-encoding", "deflate");
                        }
                    }
                    byte[] buffer= (byte[])cache;
                    context.Response.Body.Write(buffer, 0, buffer.Length);
                    context.Response.Body.Dispose();
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 计算actionUrl
        /// </summary>
        /// <param name="requestedPath"></param>
        /// <returns></returns>
        private static string GetActionUrl(string requestedPath)
        {
            int position = requestedPath.LastIndexOf('.');
            string actionUrl = "";
            if (position > 0)
            {
				int pointer = 0;
                bool hasGet = int.TryParse(requestedPath.Substring(position - 2, 2), out pointer);
                if (hasGet)
                {
                    actionUrl = requestedPath.Substring(0, pointer + 1);
                }
                else
                {
                    actionUrl = requestedPath;
                }
            }
            return actionUrl;
        }
        public static void Run(Microsoft.Owin.IOwinContext context,string rootDir, string requestedPath,int actionId)
        {
            //提取域名参数
            string host= context.Request.Host.Value;
            string[] hostName = host.Split('.');
            string subdomain = hostName.Length == 3 ? hostName[0] : "www";
            NFinal.NameValueCollection get = new NFinal.NameValueCollection();
			//提取MethodType
            NFinal.MethodType methodType = NFinal.MethodType.NONE;
            switch (context.Request.Method)
            {
                case "POST": methodType = NFinal.MethodType.POST; break;
                case "GET": methodType = NFinal.MethodType.GET; break;
                case "DELETE": methodType = NFinal.MethodType.DELETE; break;
                case "PUT": methodType = NFinal.MethodType.PUT; break;
                case "AJAX": methodType = NFinal.MethodType.AJAX; break;
                default: methodType = NFinal.MethodType.NONE; break;
            }
            //提取内容类型
			Dictionary<string,NFinal.HttpFile> files = null;
			if (methodType == NFinal.MethodType.POST)
			{
				NFinal.ContentType contentType = NFinal.ContentType.NONE;
				switch (context.Request.ContentType.Split(';')[0])
				{
					case "multipart/form-data":contentType = NFinal.ContentType.Multipart_form_data; break;
                    case "text/json":
					case "application/json":contentType = NFinal.ContentType.Application_json; break;
					case "application/x-www-form-urlencoded":contentType = NFinal.ContentType.Application_x_www_form_urlencoded; break;
                    case "application/xml":
                    case "text/xml":contentType = NFinal.ContentType.Text_xml; break;
					case "application/octet-stream":contentType = NFinal.ContentType.Application_octet_stream;break;
					default:contentType = NFinal.ContentType.NONE; break;
				}
				//提取form参数
				if (context.Request.Body!=System.IO.Stream.Null)
				{
					if (contentType == NFinal.ContentType.Application_x_www_form_urlencoded)
					{
						System.IO.StreamReader sr = new System.IO.StreamReader(context.Request.Body);
						string body = sr.ReadToEnd();
						sr.Dispose();
						if (!string.IsNullOrEmpty(body))
						{
							string[] formArray = body.Split('&', '=');
							if (formArray.Length > 1 && (formArray.Length & 1) == 0)
							{
								for (int i = 0; i < formArray.Length; i += 2)
								{
									get.Add(formArray[i], NFinal.Utility.UrlDecode(formArray[i + 1]));
								}
							}
						}
					}
					else if (contentType == NFinal.ContentType.Text_xml)
					{
						System.IO.StreamReader sr = new System.IO.StreamReader(context.Request.Body);
						string body = sr.ReadToEnd();
						sr.Dispose();
						if (!string.IsNullOrEmpty(body))
						{
							System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
							doc.LoadXml(body);
							if (doc.DocumentElement != null)
						    {
						        foreach (System.Xml.XmlElement xmlNode in doc.DocumentElement.ChildNodes)
						        {
						            get.Add(xmlNode.Name, xmlNode.Value);
						        }
						    }
						}
					}
					else if (contentType == NFinal.ContentType.Application_json)
					{
						System.IO.StreamReader sr = new System.IO.StreamReader(context.Request.Body);
						string body = sr.ReadToEnd();
						sr.Dispose();
                        IDictionary<string,object> data= SimpleJson.DeserializeObject <IDictionary<string, object>>(body);
                        foreach (var ele in data)
                        {
                            get.Add(ele.Key, ele.Value.ToString());
                        }
					}
					else if (contentType == NFinal.ContentType.Multipart_form_data)
					{
						//multipart/form-data
						string boundary =NFinal.HttpMultipart.boundaryReg.Match(context.Request.ContentType).Value;
						files = new Dictionary<string, NFinal.HttpFile>();
						var multipart = new NFinal.HttpMultipart(context.Request.Body, boundary);
						foreach (var httpMultipartBoundary in multipart.GetBoundaries())
						{
							if (string.IsNullOrEmpty(httpMultipartBoundary.Filename))
							{
								string name = httpMultipartBoundary.Name;
								if (!string.IsNullOrEmpty(name))
								{
									string value = new System.IO.StreamReader(httpMultipartBoundary.Value).ReadToEnd();
									get.Add(name, value);
								}
							}
							else
							{
								files.Add(httpMultipartBoundary.Name,new NFinal.HttpFile(httpMultipartBoundary));
							}
						}
					}
				}
			}
			//提取URL?后的参数
			if (context.Request.QueryString.HasValue)
            {
                string[] queryArray = context.Request.QueryString.Value.Split('&');
                string[] queryKeyValue = null;
                for (int i = 0; i < queryArray.Length; i++)
                {
                    queryKeyValue = queryArray[i].Split('=');
                    if (queryKeyValue.Length > 1)
                    {
                        get.Add(queryKeyValue[0],NFinal.Utility.UrlDecode(queryKeyValue[1]));
                    }
                }
            }
            //获取actionUrl,用于获取参数
			switch (actionId)
            {
					case 1:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Article.CaseAction control= new WebSite.Web.Default.Article.CaseAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Case();
						control.After();
						control.Close();
					}break;
					case 2:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Article.NewsAction control= new WebSite.Web.Default.Article.NewsAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.News();
						control.After();
						control.Close();
					}break;
					case 3:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.IndexController.IndexAction control= new WebSite.Web.Default.IndexController.IndexAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Index();
						control.After();
						control.Close();
					}break;
					case 4:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Admin.Index.indexAction control= new WebSite.Web.Default.Admin.Index.indexAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.index();
						control.After();
						control.Close();
					}break;
					case 5:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
							Regex regParameters = new Regex("/WebSite/Public/Success/([\\S]+)/([\\S]+)/([\\S]+)23.html");
							Match matParameters = regParameters.Match(requestedPath);
							get.Add("message", matParameters.Groups[1].Value);
							get.Add("url", matParameters.Groups[2].Value);
							get.Add("second", matParameters.Groups[3].Value);
						WebSite.Web.Default.Common.Public.SuccessAction control= new WebSite.Web.Default.Common.Public.SuccessAction(context);
						string message=get["message"];
						string url=get["url"];
						int second=int.TryParse(get["second"],out second)?second:0;
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Success(message,url,second);
						control.After();
						control.Close();
					}break;
					case 6:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
							Regex regParameters = new Regex("/WebSite/Public/Error/([\\S]+)/([\\S]+)/([\\S]+)21.html");
							Match matParameters = regParameters.Match(requestedPath);
							get.Add("message", matParameters.Groups[1].Value);
							get.Add("url", matParameters.Groups[2].Value);
							get.Add("second", matParameters.Groups[3].Value);
						WebSite.Web.Default.Common.Public.ErrorAction control= new WebSite.Web.Default.Common.Public.ErrorAction(context);
						string message=get["message"];
						string url=get["url"];
						int second=int.TryParse(get["second"],out second)?second:0;
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Error(message,url,second);
						control.After();
						control.Close();
					}break;
					case 7:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Common.Public.HeaderAction control= new WebSite.Web.Default.Common.Public.HeaderAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Header();
						control.After();
						control.Close();
					}break;
					case 8:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Common.Public.FooterAction control= new WebSite.Web.Default.Common.Public.FooterAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Footer();
						control.After();
						control.Close();
					}break;
					case 9:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Common.Public.NavigatorAction control= new WebSite.Web.Default.Common.Public.NavigatorAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Navigator();
						control.After();
						control.Close();
					}break;
					case 10:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Common.Public.KindEditorAction control= new WebSite.Web.Default.Common.Public.KindEditorAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.KindEditor();
						control.After();
						control.Close();
					}break;
					case 11:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Common.Public.DockAction control= new WebSite.Web.Default.Common.Public.DockAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.Dock();
						control.After();
						control.Close();
					}break;
					case 12:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
						WebSite.Web.Default.Common.VCode.GetVerifyImageAction control= new WebSite.Web.Default.Common.VCode.GetVerifyImageAction(context);
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.GetVerifyImage();
						control.After();
						control.Close();
					}break;
					case 13:
					{
						context.Response.ContentType = "text/html; charset=utf-8";
							Regex regParameters = new Regex("/WebSite/VCode/VCheck/([\\S]+)21.html");
							Match matParameters = regParameters.Match(requestedPath);
							get.Add("vcode", matParameters.Groups[1].Value);
						WebSite.Web.Default.Common.VCode.VCheckAction control= new WebSite.Web.Default.Common.VCode.VCheckAction(context);
						string vcode=get["vcode"];
						control._methodType = methodType;
						control._webContext = context;
						control._subdomain = subdomain;
						control._url=requestedPath;
						control._get = get;
						control._files = files;
						control._app="/WebSite";
						control.Before();
						control.VCheck(vcode);
						control.After();
						control.Close();
					}break;

                default: break;
            }
        }
    }
#endif
}